package waal.pc.frontend.tiles;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Queue;

import javax.swing.JCheckBox;
import javax.swing.JPanel;

import waal.pc.backend.channels.Channel;
import waal.pc.backend.channels.ChannelDataListener;
import waal.pc.backend.dataPoints.DataPoint;
import waal.pc.backend.module.Module;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.general.DatasetChangeEvent;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;

public class LinePlotTile extends ModuleTile implements UpdateableTile, ChannelDataListener, ActionListener {

	private static final long serialVersionUID = 1L;
	private Map<Channel, XYSeries> channelSeries;
	private Map<Channel, Queue<DataPoint>> channelQueue;
	private DatasetChangeEvent datasetChangeEvent;
	private XYPlot polt;
	//private Hub hub;
	private XYItemRenderer renderer;

	private ChartPanel chartpanel;
	
	public LinePlotTile() {
		super("MultiLine");
		this.setLayout(new BorderLayout());
	}

	@Override
	public Tile getTile(Module module) {
		this.initTile(module);
		XYSeriesCollection dataset = this.createDataSet(module);
		this.datasetChangeEvent = new DatasetChangeEvent(dataset, dataset);
		//JFreeChart chart = createChart(dataset, module.getName(), module.getUnit());
		JFreeChart chart = createChart(dataset, "", module.getUnit());
		this.polt = (XYPlot) chart.getPlot();
		this.renderer = this.polt.getRenderer();
		dataset.removeChangeListener(this.polt);
		this.chartpanel = new ChartPanel(chart);
		this.chartpanel.setPreferredSize(new Dimension(300, 300));
		this.add(this.chartpanel, BorderLayout.CENTER);
		this.setPreferredSize(new Dimension(300,300));
		this.updateTile();
		this.setMinimumSize(new Dimension(100, 100));
		
		return this;
	}
	
	private XYSeriesCollection createDataSet(Module module) {
		this.channelSeries = new HashMap<Channel, XYSeries>();
		this.channelQueue = new HashMap<Channel, Queue<DataPoint>>();
		int maximumItems = 2000;
		XYSeriesCollection dataset = new XYSeriesCollection();
		Channel ch;
		XYSeries xys;
		JCheckBox cb;
		int chn;
		Iterator<Channel> ic = module.getChannels().iterator();
		JPanel buttonPanel = new JPanel(new FlowLayout());
		while(ic.hasNext()) {
			ch = ic.next();
			if(ch.isActive()) {
				chn = ch.getChannelNumber();
				cb = new JCheckBox("Ch" + (chn+1));
				cb.setToolTipText(ch.toString());
				cb.setActionCommand("" + chn);
				cb.addActionListener(this);
				cb.setSelected(true);
				buttonPanel.add(cb);
				xys = new XYSeries("Ch" + (chn+1));
				xys.setMaximumItemCount(maximumItems);
				dataset.addSeries(xys);
				this.channelSeries.put(ch, xys);
				this.channelQueue.put(ch, ch.getMyQueue(this));
			}
		}
		this.add(buttonPanel, BorderLayout.SOUTH);
		return dataset;
	}
	
	private JFreeChart createChart(XYSeriesCollection dataset, String name, String unit) {
		JFreeChart chart = ChartFactory.createXYLineChart(
				name, // chart title
				"time", // x axis label
				unit, // y axis label
				dataset, // data
				PlotOrientation.VERTICAL,
				true, // include legend
				true, // tooltips
				false // urls
				);
		return chart;
	}
		
	@Override
	public ModuleTile clone() {
		return new LinePlotTile();
	}

	@Override
	public boolean isDigital() {
		return false;
	}

	@Override
	public boolean isInput() {
		return true;
	}

	@Override
	public boolean isOutput() {
		return false;
	}

	@Override
	public boolean isUpdateAble() {
		return true;
	}

	@Override
	public void updateTile() {
		if(this.active) {
			Channel ch;
			XYSeries xys;
			DataPoint d, d2;
			Queue<DataPoint> q;
			Iterator<Channel> ic = this.channelQueue.keySet().iterator(); 
			while(ic.hasNext()) {
				ch = ic.next();
				//Log.addToDebug(3, "LinePlotTile", "updateTile", "check data for channel: " + ch.getID());
				xys = this.channelSeries.get(ch);
				q = this.channelQueue.get(ch);
				if( q.isEmpty()) {
					//Log.addToDebug(3, "LinePlotTile", "updateTile", "channel: " + ch.getID() + " has no data");
					xys.add((xys.getMaxX()+0.1), ch.getLastValue());
				} else {
					//Log.addToDebug(3, "LinePlotTile", "updateTile", "channel: " + ch.getID() + " has Datapoints: " + q.size());
					d = q.poll();
					//System.out.print(".");
					while(!q.isEmpty()) {
						//System.out.println("Size" + q.size());
						d2 = q.poll();
						xys.add(d.getTime(), d.getValue(), false);
						d = d2;
					}
					xys.add(d.getTime(), d.getValue());
				}
			}
			this.polt.datasetChanged(this.datasetChangeEvent);
		}
	}

	@Override
	public void channelGetKilled(Channel ch) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void setDimension(int width, int heigh) {
		System.out.println("+");
		this.chartpanel.setPreferredSize(new Dimension(width-10, heigh-10));
		//this.setPreferredSize(new Dimension(width, heigh));
		
		
	}

	@Override
	public void closeTile() {
		this.active = false;
		this.channelQueue.clear();
		this.channelSeries.clear();		
	}
	

	@Override
	protected void hubStart() {
		for(Iterator<XYSeries> is = this.channelSeries.values().iterator(); is.hasNext(); ) {
			is.next().clear();
		}
		this.polt.datasetChanged(this.datasetChangeEvent);		
	}
	

	@Override
	protected void hubStop() {
				
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		int channel = Integer.parseInt(e.getActionCommand());
		
		if (channel >= 0)
		{
			boolean flag = renderer.getItemVisible(channel, 0);
			renderer.setSeriesVisible(channel, new Boolean(!flag));
		}
		
	}

}
